package com.culturalCenter.dataCenter.schedule.user;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.culturalCenter.dataCenter.Utils.*;
import com.culturalCenter.dataCenter.customEntity.user.pull.UserActivityEntity;
import com.culturalCenter.dataCenter.customEntity.user.pull.UserEntity;
import com.culturalCenter.dataCenter.customEntity.user.pull.UserFootprintEntity;
import com.culturalCenter.dataCenter.entity.user.User;
import com.culturalCenter.dataCenter.entity.user.UserActivity;
import com.culturalCenter.dataCenter.entity.user.UserFootprint;
import com.culturalCenter.dataCenter.entity.user.UserLocationPicture;
import com.culturalCenter.dataCenter.mapper.user.UserActivityMapper;
import com.culturalCenter.dataCenter.mapper.user.UserFootprintMapper;
import com.culturalCenter.dataCenter.mapper.user.UserLocationPictureMapper;
import com.culturalCenter.dataCenter.mapper.user.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 定时任务_用户_拉取
 *
 * @author 方治森
 * @since 2022/4/20
 */
@Component
@Slf4j
@Async("dataThreadExecutor")
public class UserDataPull {

    private String user_timestamp1;
    private long user_timestamp2;
    private long user_timestamp3;
    private long user_timestamp4;
    private final long size = 500;
    @Value("${tuchuang.hostname}")
    private String hostname;
    @Value("${placeManage.hostname}")
    private String placeManageHost;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserFootprintMapper userFootprintMapper;
    @Resource
    private UserActivityMapper userActivityMapper;
    @Resource
    private UserLocationPictureMapper userLocationPictureMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RedissonClient redisson;

    /**
     * 初始化时间戳
     */
    @PostConstruct
    public void initTimestamp() {
        user_timestamp1 = !redisUtil.redisTemplate.hasKey("user_timestamp1") ? null : redisUtil.get("user_timestamp1");
        user_timestamp2 = !redisUtil.redisTemplate.hasKey("user_timestamp2") ? 0 : Long.parseLong(redisUtil.get("user_timestamp2"));
        user_timestamp3 = !redisUtil.redisTemplate.hasKey("user_timestamp3") ? 0 : Long.parseLong(redisUtil.get("user_timestamp3"));
        user_timestamp4 = !redisUtil.redisTemplate.hasKey("user_timestamp4") ? 0 : Long.parseLong(redisUtil.get("user_timestamp4"));

        // for test
        // user_timestamp1 = null;
        // user_timestamp2 = 0;
        // user_timestamp3 = 0;
        // user_timestamp4 = 0;
        // for (int i = 1; i <= 4; i++) {
        //     redisUtil.del("user_lock" + i);
        // }
    }

    /**
     * 获取返回数据中的data
     */
    public String getData(String uri, Map<String, Object> param) {
        try {
            String url = hostname + uri + "?" + ClassUtil.setParamString(param);
            String responseJson = restTemplate.getForObject(url, String.class);
            return JSON.parseObject(responseJson).getString("data");
        } catch (HttpServerErrorException e) {
            log.error("TCC综合管理平台服务端异常，请联系TCC相关人员");
            throw e;
        }
    }

    /**
     * 获取返回数据中的data（场地管理）
     */
    public String getSiteData(String uri, Map<String, Object> param) {
        String url = placeManageHost + uri + "?" + ClassUtil.setParamString(param);
        String responseJson = restTemplate.getForObject(url, String.class);
        return JSON.parseObject(responseJson).getString("data");
    }

    /**
     * 用户(cdc_user)
     */
//    @Scheduled(cron = "${cron.userPull}")
//     @Scheduled(cron = "${cron.test}")
    public void pullUserList() {
        String lockKey = "user_lock1";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("'cdc_user'开始拉取。。。。。");

            Map<String, Object> param = new TreeMap<>();
            long current = 1;
            /*SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date afterTime = df1.parse(user_timestamp1);
            System.out.println(afterTime);*/
            param.put("afterTime", user_timestamp1); //todo 不能用时间戳 要用date 2014-01-01 00:00:00
            param.put("isPageView", true);
            param.put("current", current);
            param.put("size", size);
            String data = getData("/api/tcc-user-center/client-api/userCenter/listInfo", param);
            long pages = Long.parseLong(JSON.parseObject(data).getString("pages"));
            List<User> userList = new ArrayList<>();
            insertUserList(data, userList);
            while (current < pages) {
                current++;
                param.put("current", current);
                insertUserList(getData("/api/tcc-user-center/client-api/userCenter/listInfo", param), userList);
                userMapper.insertBatch(userList);
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                List<Date> timeList = userList.stream().map(User::getUpdateTime).filter(Objects::nonNull).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(timeList)) {
                    redisUtil.set("user_timestamp1", df.format(Collections.max(timeList)));
                }
                userList.clear();
            }

            log.info("cdc_user拉取完毕。。。。。");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    public void insertUserList(String data, List<User> userList) {
        IdCardGenerator idCardGenerator = new IdCardGenerator();
        List<UserEntity> dataList = JSON.parseArray(JSON.parseObject(data).getString("records"),
                UserEntity.class);
        if (CollUtil.isNotEmpty(dataList)) {
            for (UserEntity dataElement : dataList) {
                User user = new User();
                user.setRefId(String.valueOf(dataElement.getId()));
                /*
                  TODO 由于图创对身份证进行了脱敏，因此先我们随机生成身份证
                 */
                String idCard = idCardGenerator.generate();
                // String idCard = dataElement.getIdCard();
                /*
                  通过身份证获取年龄&星座&生肖
                 */
                if (StrUtil.isNotEmpty(idCard)) {
//                    user.setIDCard(idCard);
                    String regEx = "-";
                    Pattern p = Pattern.compile(regEx);
                    Matcher m = p.matcher(idCard);
                    if (!m.find()) {
                        int year = Integer.parseInt(idCard.substring(6, 10));
                        int month = Integer.parseInt(idCard.substring(10, 12));
                        int day = Integer.parseInt(idCard.substring(12, 14));
                        user.setAge(Integer.parseInt(DateFormatUtil.getYear(new Date())) - year);
                        user.setZodiacChina(DateUtil.getChineseZodiac(year));
                        user.setZodiacForeign(DateUtil.getZodiac(month - 1, day));
                        user.setBirthday(DateFormatUtil.parseIDCard(idCard.substring(6, 14)));
                    }
                }
                user.setLevel(StringUtils.isEmpty(dataElement.getLevel()) ? null : dataElement.getLevel());
                user.setPhone(StringUtils.isEmpty(dataElement.getMobilePhone()) ? null : dataElement.getMobilePhone());
                user.setNickName(StringUtils.isEmpty(dataElement.getNickName()) ? null
                        : CharAscii.removeFourChar(dataElement.getNickName()));
                user.setLicencePlate(
                        StringUtils.isEmpty(dataElement.getNumberPlate()) ? null : dataElement.getNumberPlate());
                user.setName(StringUtils.isEmpty(dataElement.getRealName()) ? null : dataElement.getRealName());
                user.setType(dataElement.getVerifyTag() == 1 ? "实名" : "未实名");
                user.setWeChatId(
                        StringUtils.isEmpty(dataElement.getWechatOpenid()) ? null : dataElement.getWechatOpenid());
                user.setSex(dataElement.getGender() == 0 ? "女" : "男");
                user.setPhoto(StringUtils.isEmpty(dataElement.getHeadPic()) ? null : dataElement.getHeadPic());
                user.setPoint(dataElement.getCredit());
                user.setCreateTime(dataElement.getCreateTime());
                user.setUpdateTime(dataElement.getUpdateTime());
                user.setIsBlackList(dataElement.getStatus());
                user.setStatus(0);
                userList.add(user);
            }
        }
    }

    /**
     * 用户浏览记录(cdc_user_footprint)
     */
//    @Scheduled(cron = "${cron.userPull}")
    // @Scheduled(cron = "${cron.test}")
    public void pullUserBrowsingRecord() {
        String lockKey = "user_lock2";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("'cdc_user_footprint'开始拉取。。。。。");

            Map<String, Object> param = new TreeMap<>();
            long current = 1;
            param.put("updateTimestamp", user_timestamp2);
            param.put("current", current);
            param.put("size", size);
            String data = getData("/api/tcc-mes-service/client-api/user/browsingRecord/listActivityAndTrainPage",
                    param);
            long pages = Long.parseLong(JSON.parseObject(data).getString("pages"));
            List<UserFootprint> userFootprintList = new ArrayList<>();
            for (; current <= pages; current++) {
                param.put("current", current);
                insertUserBrowsingRecord(
                        getData("/api/tcc-mes-service/client-api/user/browsingRecord/listActivityAndTrainPage", param),
                        userFootprintList);
                userFootprintMapper.insertBatch(userFootprintList);
                redisUtil.set("user_timestamp2",
                        Long.toString(userFootprintList.stream().max(Comparator.comparing(UserFootprint::getUpdateTime)).get().getUpdateTime().getTime()));
                userFootprintList.clear();
            }

            log.info("'cdc_user_footprint'拉取完毕。。。。。");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    private void insertUserBrowsingRecord(String data, List<UserFootprint> userFootprintList) {
        List<UserFootprintEntity> dataList = JSON.parseArray(JSON.parseObject(data).getString("records"),
                UserFootprintEntity.class);
        if (CollUtil.isNotEmpty(dataList)) {
            for (UserFootprintEntity dataElement : dataList) {
                UserFootprint userFootprint = new UserFootprint();
                userFootprint.setRefId(String.valueOf(dataElement.getId()));
                userFootprint.setUserId(String.valueOf(dataElement.getUserId()));
                userFootprint.setActivityId(String.valueOf(dataElement.getObjId()));
                userFootprint.setActivityName(dataElement.getObjTitle());
                userFootprint.setActivityType(dataElement.getModule().equals("activity") ? 1 : 2);
                userFootprint.setClientType(dataElement.getEntranceSource());
                userFootprint.setTime(dataElement.getBrowsingTime());
                userFootprint.setUpdateTime(dataElement.getBrowsingTime());
                userFootprintList.add(userFootprint);
            }
        }
    }

    /**
     * 用户活动培训参与记录(cdc_user_activity)
     */
//    @Scheduled(cron = "${cron.userPull}")
    // @Scheduled(cron = "${cron.test}")
    public void pullUserActivityAndTrain() {
        String lockKey = "user_lock3";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("'cdc_user_activity'开始拉取。。。。。");

            Map<String, Object> param = new HashMap<>();
            long current = 1;
            param.put("updateTimestamp", user_timestamp3);
            param.put("current", current);
            param.put("size", size);
            String data = getData("/api/tcc-mes-service/client-api/user/joinRecord/listActivityAndTrainPage", param);
            long pages = Long.parseLong(JSON.parseObject(data).getString("pages"));
            List<UserActivity> userActivityList = new ArrayList<>();
            for (; current <= pages; current++) {
                param.put("current", current);
                insertUserActivityAndTrain(getData("/api/tcc-mes-service/client-api/user/joinRecord/listActivityAndTrainPage", param),
                        userActivityList);
                userActivityMapper.insertBatch(userActivityList);
                redisUtil.set("user_timestamp3",
                        Long.toString(userActivityList.stream().max(Comparator.comparing(UserActivity::getUpdateTime)).get().getUpdateTime().getTime()));
                userActivityList.clear();
            }

            log.info("cdc_user_activity拉取完毕。。。。。");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    private void insertUserActivityAndTrain(String data, List<UserActivity> userActivityList) {
        List<UserActivityEntity> dataList = JSON.parseArray(JSON.parseObject(data).getString("records"),
                UserActivityEntity.class);
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (UserActivityEntity dataElement : dataList) {
                UserActivity userActivity = new UserActivity();
                if (ObjectUtil.isNotEmpty(dataElement.getUserId())) {
                    userActivity.setRefId(String.valueOf(dataElement.getId()));
                    userActivity.setUserId(String.valueOf(dataElement.getUserId()));
                    userActivity.setActivityId(String.valueOf(dataElement.getObjId()));
                    userActivity.setObjRoundId(String.valueOf(dataElement.getObjRoundId()));
                    userActivity.setActivityName(dataElement.getObjTitle());
                    userActivity.setActivityType("culture_activity".equals(dataElement.getModule()) ? 1 : 2);
                    userActivity.setContentType(dataElement.getObjCategory());
                    userActivity.setEntranceSource(dataElement.getEntranceSource());
                    userActivity.setBeginTime(dataElement.getStartTime());
                    userActivity.setEndTime(dataElement.getEndTime());
                    userActivity.setRegisterTime(dataElement.getRegisterTime());
                    userActivity.setSignTime(dataElement.getSignTime());
                    userActivity.setSignInSource(dataElement.getSignInSource());
                    userActivity.setAttendanceStatus(dataElement.getAttendanceStatus());
                    if (dataElement.getRegisterTime() != null) {
                        userActivity.setStatus("已报名");
                    }
                    if (dataElement.getSignTime() != null) {
                        userActivity.setStatus("已参加");
                    }
                    userActivity.setUpdateTime(dataElement.getUpdateTime());
                    userActivityList.add(userActivity);
                }
            }
        }
    }

    /**
     * 用户位置图片(cdc_user_location_picture场地管理)
     */
//    @Scheduled(cron = "${cron.userPull}")
    // @Scheduled(cron = "${cron.test}")
    public void pullUserLocationPicture() {
        String lockKey = "user_lock4";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            log.info("'cdc_user_location_picture'开始拉取。。。。。");

            Map<String, Object> param = new HashMap<>();
            param.put("date", DateUtil.date(user_timestamp4 * 1000));
            String data = getSiteData("/v1/app/camera/getCapturePicture", param);
            JSONObject object = JSONUtil.parseObj(data);
            long pages = object.getLong("pages");
            List<UserLocationPicture> userLocationPictureList = new ArrayList<>();
            for (long current = 1; current <= pages; current++) {
                param.put("pageNum", current);
                insertUserLocationPicture(getSiteData("/v1/app/camera/getCapturePicture", param),
                        userLocationPictureList);
                userLocationPictureMapper.insertBatch(userLocationPictureList);
                redisUtil.set("user_timestamp4",
                        Long.toString(userLocationPictureList.stream().max(Comparator.comparing(UserLocationPicture::getCreateTime)).get().getCreateTime().getTime()));
                userLocationPictureList.clear();
            }
            log.info("'cdc_user_location_picture'拉取完毕。。。。。");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    private void insertUserLocationPicture(String data, List<UserLocationPicture> userLocationPictureList) {
        userLocationPictureList
                .addAll(JSON.parseArray(JSON.parseObject(data).getString("list"), UserLocationPicture.class));
        userLocationPictureList.forEach(item -> {
            if (StrUtil.isNotEmpty(item.getPhone())) {
                String phone = item.getPhone();
                User user = userMapper.queryUserIdAndIDCard(phone);
                if (Objects.nonNull(user)) {
                    item.setUserId(user.getRefId());
                    item.setIDCard(user.getIDCard());
                }
            }
        });
    }

}
